package com.easy.tool.utils.bean;

import com.easy.tool.anno.BeanDes;
import com.easy.tool.anno.MethodDes;
import org.apache.log4j.Logger;

import java.lang.reflect.Field;
import java.util.*;

/**
 * @author 高俊
 * @create 2021-09-2021/9/2-21:26
 */
@BeanDes(name = "bean的操作类", des = "对象之间的copy，以及对象转map，map转对象等")
public class BeanUtils {

    private static Logger logger = Logger.getLogger(BeanUtils.class);

    /**
     * copy对象
     * @param src 源对象
     * @param target 目标对象
     */
    @MethodDes(des = "copy对象",param = {"arg0-> src：源对象","arg1-> target：目标对象"})
    public static void copy(Object src,Object target){
        // 获取指定类属性的键值对
        Map<Object,Object> srcMap = getObjMap(src);
        // 设置指定对象值
        setObjVal(target,srcMap);
    }

    /**
     * copy对象
     * @param src 源对象
     * @param clazz 目标对象
     */
    @MethodDes(des = "copy对象",param = {"arg0-> src：源对象","arg1-> clazz：目标对象"})
    public static <T> T copy(Object src,Class<T> clazz){
        T to = null;
        // 获取指定类属性的键值对
        Map<Object,Object> srcMap = getObjMap(src);
        try {
            // 设置指定对象值
            to = (T) setObjVal(clazz.newInstance(), srcMap);
            return to;
        }catch (Exception e){
            logger.error("执行copy操作异常");
        }
        return to;
    }

    /**
     * copy集合
     * @param list
     * @param clazz
     * @param <T>
     * @param <S>
     * @return
     */
    @MethodDes(des = "copy集合",param = {"arg0-> list：源对象.List类型","arg1-> clazz：目标对象Class"})
    public static <T,S> List<S> copyList(List<T> list,Class<S> clazz){
        List<S> newList = new ArrayList<>();
        for (T t : list) {
            S s = copy(t, clazz);
            newList.add(s);
        }
        return newList;
    }


    /**
     * 获取对象值 返回Map
     * @param src
     * @return
     */
    @MethodDes(des = "获取对象值 返回Map",param = {"arg0-> src：指定对象"})
    public static Map<Object,Object> getObjMap(Object src){
        HashMap<Object, Object> targetMap = new HashMap<>(20);

        Class srcClz = src.getClass();
        Field[] fields = srcClz.getDeclaredFields();
        getObjMapSon(fields,src,targetMap);

        // 获取父类属性
        Class superclass = srcClz.getSuperclass();
        getObjMapSupper(superclass,src,targetMap);
        return targetMap;
    }

    /**
     * 通过list集合包装的map装对象
     * @param list
     * @param <E>
     * @return
     */
    @MethodDes(des = "通过list集合包装的map装对象",param = {"arg0-> list：源对象List类型","arg1-> clazz：目标对象Class"})
    public static <E,T,S> List<E> mapToObject(List<Map<T,S>> list,Class<E> clazz){
        List<E> resultList = new ArrayList<>();
        for (Map<T,S> tsMap : list) {
            E e = mapToObject(tsMap, clazz);
            resultList.add(e);
        }
        return resultList;
    }
    /**
     * list中以key-value的形势储存了对象中的每个属性的键值对
     * @param list
     * @param <E>
     * @return
     */
    @MethodDes(des = "ist中以key-value的形势储存了对象中的每个属性的键值对",param = {"arg0-> list：源对象List类型","arg1-> clazz：目标对象Class"})
    public static <E,T,S> E mapListToObject(List<Map<T,S>> list,Class<E> clazz){
        HashMap<Object ,Object> map = new HashMap<>();
        for (Map<T,S> tsMap : list) {
            map.put(tsMap.get("name"),tsMap.get("value"));
        }
        return mapToObject(map, clazz);
    }

    /**
     * map转对象
     * @param map
     * @param <E>
     * @return
     */
    @MethodDes(des = "map转对象",param = {"arg0-> map：源对象map类型","arg1-> clazz：目标Class。Class类型"})
    public static <E,T,S> E mapToObject(Map<T,S> map,Class<E> clazz){
        E es = null;
        try {
            es = clazz.newInstance();
        }catch (Exception e){
            logger.error("反射实例化报错："+e.getMessage());
        }
        Iterator<Map.Entry<T, S>> iterator = map.entrySet().iterator();
        while (iterator.hasNext()){
            Map.Entry<T, S> entry = iterator.next();
            try {
                Field field = clazz.getDeclaredField(entry.getKey().toString());
                field.setAccessible(true);
                field.set(es,entry.getValue());
                // 删除当前key-value
                iterator.remove();
            }catch (Exception e){
                logger.warn("设置属性（"+entry.getKey()+"）报错："+e.getMessage());
            }
        }
        Class<? super E> Superclass = clazz.getSuperclass();
        if (Superclass.getDeclaredFields().length != 0){
            setObjValSupper(clazz.getSuperclass(),es,map);
        }
        return es;
    }

    /**
     * 对象集合转map集合
     * @param list
     * @return
     * @param <T>
     */
    public static <T> List<Map<Object, Object>> objectListToMapList(List<T> list){
        List<Map<Object, Object>> mapList = new ArrayList<>(10);
        for (T t : list) {
            mapList.add(getObjMap(t));
        }
        return mapList;
    }


    /* ********************************************************************************************************************* */

    /**
     *  获取对象值的公用方法
     * @param fields
     * @param src
     * @param srcMap
     */
    private static void getObjMapSon(Field[] fields,Object src,HashMap<Object, Object> srcMap){
        for (Field field : fields) {
            field.setAccessible(true);
            try {
                Object value = field.get(src);
                if (null != value){
                    srcMap.put(field.getName(),value);
                }
                srcMap.put(field.getName(),value);
            }catch (Exception e){
                logger.error("方法未找到:" + e.getMessage());
            }


        }

    }

    /**
     * 设置父类对象值
     * @param superclass    父类Class
     * @param src           源对象
     * @param srcMap        目标对象
     * @return
     */
    private static int getObjMapSupper(Class superclass,Object src,HashMap<Object, Object> srcMap){
        if (superclass.getDeclaredFields().length != 0){
            Field[] fs = superclass.getDeclaredFields();
            getObjMapSon(fs,src,srcMap);

            superclass = superclass.getSuperclass();
            if (superclass.getDeclaredFields().length != 0){
                getObjMapSupper(superclass,src,srcMap);
            }else {
                return 0;
            }

        }

        return 0;
    }





    /**
     * 设置对象的值
     * @param target
     * @param srcMap
     * @return
     */
    private static Object setObjVal(Object target,Map<Object,Object> srcMap){
        Class targetClz = target.getClass();
        Field[] tarField = targetClz.getDeclaredFields();
        setObjValSon(tarField,target,srcMap);
        // 设置父类属性值
        Class superclass = targetClz.getSuperclass();
        setObjValSupper(superclass,target,srcMap);
        return target;
    }

    /**
     * 设置对象值的公用方法
     * @param fields
     * @param target
     * @param srcMap
     */
    private static <T,S> void setObjValSon(Field[] fields,Object target,Map<T,S> srcMap){
        String fieldName = "";
        for (Field field : fields) {
            try {
                fieldName = field.getName();
                Object value = srcMap.get(fieldName);
                if (value == null) {
                    continue;
                }
                field.setAccessible(true);


                field.set(target, value);
            } catch (Exception e) {
                if (!"serialVersionUID".equals(fieldName)){
                    logger.warn("copy对象:" + fieldName + "属性有未赋上值的属性");
                }

            }
        }

    }

    /**
     * 设置 父类属性值
     * @param superclass  父类class
     * @param target        目标对象
     * @param srcMap        源对象
     * @return
     */
    private static <T,S> int setObjValSupper(Class superclass,Object target,Map<T,S> srcMap){
        if (superclass.getDeclaredFields().length != 0){
            Field[] fs = superclass.getDeclaredFields();
            setObjValSon(fs,target,srcMap);
            superclass = superclass.getSuperclass();
            if (superclass.getDeclaredFields().length != 0){
                setObjValSupper(superclass,target,srcMap);
            }else {
                return 0;
            }
        }
        return 0;
    }
}
